/***************************************************************************
 * 
 * Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved
 * $Id$ 
 * 
 **************************************************************************/

/**
 * @file ObjectPool.h
 * @author liutongren(liutongren@baidu.com)
 * @date 2015/08/08 13:59:48
 * @version $Revision$ 
 * @brief 
 *  
 **/
#ifndef _LIUTONGREN_UTIL_OBJECTPOOL_H
#define _LIUTONGREN_UTIL_OBJECTPOOL_H
#include <pthread.h>
#include <list>
namespace util {
    template <typename T>
        class ObjectPool{
        public:
            typedef typename std::list<T*>::iterator iterator_T_ptr;
        public:
            ObjectPool(void);
            ObjectPool(size_t number);
            virtual ~ObjectPool();
            T* get_ptr();
            bool give_back(T* object_ptr);
            int size();
            void init(size_t number);
        private:
            std::list<T*> *_object_list;
            pthread_mutex_t _object_locker;
        };

  
    template <typename T> 
        ObjectPool<T>::ObjectPool(void) {
            init(0);
        }


    template <typename T> 
        ObjectPool<T>::ObjectPool(size_t number) {
            init(number);
        }
    
    template <typename T> 
        void ObjectPool<T>::init(size_t number) {
            _object_list = new std::list<T*>; 
            pthread_mutex_init(&_object_locker, NULL);
            if (number > 0) {
                for (int i = 0; i != number; ++i) {
                    _object_list->push_back(new T);
                }
            }
        }

    template <typename T>    
        ObjectPool<T>::~ObjectPool(){
            pthread_mutex_destroy(&_object_locker);
            if (_object_list != NULL) {
                iterator_T_ptr it;
                for (it = _object_list->begin(); it != _object_list->end(); ++it) {
                    T* ptr_t = *it;                    
                    delete ptr_t;
                    ptr_t = NULL;
                } 
                delete _object_list;
                _object_list = NULL;
            }

        }

    template <typename T>
        T* ObjectPool<T>::get_ptr() {
            if (_object_list->empty()) {
                return new T; 
            } else {
                pthread_mutex_lock(&_object_locker);
                T *t = _object_list->front();
                _object_list->pop_front();
                pthread_mutex_unlock(&_object_locker);
                return t;
            }
        }
    
    template <typename T>
        bool ObjectPool<T>::give_back(T *object_ptr) {
            if (object_ptr == NULL) {
                return false;
            }
            std::cout << "before" << std::endl;
            pthread_mutex_lock(&_object_locker);
            std::cout << "size" << this->size() << std::endl;
            _object_list->push_back(object_ptr); 
            pthread_mutex_unlock(&_object_locker);
            std::cout << "after" << std::endl;
            return true;
        }
 
    template <typename T>
        int ObjectPool<T>::size() {
            if (NULL == _object_list) {
                return -1; 
            } else {
                return _object_list->size();
            } 
        }


}
#endif  // ObjectPool_H

/* vim: set ts=4 sw=4 sts=4 tw=100 */
